home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / c / xmsif15.zip / XMSIF.DOC < prev    next >
Text File  |  1993-05-16  |  44KB  |  975 lines

  1.                                  XMSIF
  2.                       C Interface to XMS Functions
  3.                            XMSIF version 1.5
  4.                           by James W. Birdsall
  5.                                 05/16/93
  6.  
  7.  
  8. 0. CONTENTS
  9. -----------
  10.  
  11.    0.     CONTENTS
  12.    I.     INTRODUCTION
  13.     I.1    WHAT IS SUPPORTED
  14.     I.2    COPYRIGHT, LICENSE, AND WARRANTY DISCLAIMER
  15.    II.    COMPILING AND LINKING WITH THE LIBRARIES
  16.     II.1   WITH C
  17.     II.2   WITH C++
  18.     II.3   XMSTEST, THE EXAMPLE PROGRAM
  19.    III.   PROGRAMMING WITH XMSIF
  20.     III.1  INITIALIZING THE LIBRARY
  21.     III.2  ORDINARY USE
  22.     III.3  TIPS ON USING EMBS
  23.     III.4  TIPS ON USING UMBS
  24.     III.5  OTHER TIPS
  25.     III.6  FUNCTION GROUPINGS
  26.    IV.    LIBRARY REFERENCE
  27.     IV.1   GLOBAL VARIABLES
  28.     IV.2   EMB FUNCTIONS
  29.     IV.3   UMB FUNCTIONS
  30.    V.     ERROR CODES
  31.     V.1    INTERNAL ERRORS
  32.     V.2    XMS DRIVER ERRORS
  33.    VI.    THE END
  34.     VI.1   ACKNOWLEDGEMENTS
  35.  
  36.  
  37. I. INTRODUCTION
  38. ---------------
  39.  
  40.    XMSIF provides a high-level interface to XMS control functions for
  41. common operations such as allocating and freeing XMS extended memory
  42. blocks (EMBs) and upper memory blocks (UMBs), and copying data to and
  43. from EMBs. A raw interface to the driver has been included to allow more
  44. convenient access to driver functions not otherwise supported.
  45.  
  46.    XMSIF is written in assembly language for speed and assembled with
  47. Borland's Turbo Assembler (TASM) 2.5. The source code is not compatible
  48. with the Microsoft Assembler (MASM).
  49.  
  50.  I.1 WHAT IS SUPPORTED
  51.  ---------------------
  52.  
  53.    XMSIF expressly supports the Microsoft eXtended Memory Specification
  54. (XMS) versions 2.0 and 3.0. Versions below 2.0 are not supported.
  55. Versions above 3.0 are supported as 3.0.
  56.  
  57.    XMSIF supports tiny, small, medium, compact, large, and huge memory
  58. models. The small model library supports both tiny and small models, so
  59. no library is provided specifically for tiny model.
  60.  
  61.    XMSIF supports any version of Turbo C, Turbo C++, or Borland C++, in
  62. both C and C++ modes, and Microsoft C 6.00/A and C/C++ 7.0. XMSIF has
  63. been tested with Borland C++ 2.0, Turbo C 2.0, Microsoft C 6.00A, and
  64. Microsoft C/C++ 7.0 in all of the supported memory models. XMSIF should
  65. work with earlier versions of Microsoft C and any other MS-DOS C
  66. compiler that 1) uses compatible parameter passing and return methods
  67. and 2) can use standard-format libraries.
  68.  
  69.  I.2 COPYRIGHT, LICENSE, AND WARRANTY DISCLAIMER
  70.  -----------------------------------------------
  71.  
  72.    XMSIF is not in the public domain. All the files are copyright 1991,
  73. 1992, 1993 by James W. Birdsall, all rights reserved. Permission is
  74. granted to do the following:
  75.  
  76.         You may freely redistribute this archive, so long as it contains
  77.         all the files listed in the file MANIFEST, intact and
  78.         unmodified.
  79.  
  80.         You may use the libraries in programs for your own use. You may
  81.         not distribute programs linked with these libraries.
  82.  
  83.    Payment of the $5 shareware registration fee ($50 for commercial use)
  84. grants the following license, in addition to the permissions listed
  85. above:
  86.  
  87.         You may request the source to XMSIF. You may modify the source
  88.         as necessary for use in your programs. However, you may not
  89.         redistribute either the original or modified source. There is no
  90.         additional charge for source.
  91.  
  92.         You may distribute programs linked with either the original
  93.         libraries or libraries generated from source you have modified,
  94.         without royalty, provided you (a) do not alter or remove
  95.         copyright notices contained therein and (b) you indemnify, hold
  96.         harmless, and defend the author from and against any claims or
  97.         lawsuits, including attorney's fees, that arise or result from
  98.         the use or distribution of your software product. 
  99.  
  100. For the purposes of this license, commercial use is defined as use by an
  101. incorporated entity in a software product that is regarded as the
  102. product of the corporation, no matter how the software product is
  103. distributed, but only if 100 or more copies of the product are expected
  104. to be made.
  105.  
  106.    Registered users will also receive update notices and bug reports,
  107. and are entitled to use future versions without further payment.
  108.  
  109.    The contents of the distribution archive, and all other related
  110. files, information, and services are provided "as is" and without
  111. warranty. To the extent permitted by applicable law, the author
  112. disclaims all warranties, express or implied, including but not limited
  113. to, any implied warranty of merchantability or fitness for a particular
  114. purpose. While effort has been made to ensure that the files, information,
  115. and services are accurate and correct, the author shall not be liable
  116. for damages arising out of the use of or inability to use this product,
  117. including but not limited to, loss of profit, data, or use of this
  118. software, or special, incidental, or consequential damages or other
  119. similar claims, even if the author has been specifically advised of the
  120. possibility of such damages. Some states do not allow the exclusion of
  121. incidental or consequential damages, so the foregoing limitation may not
  122. apply to you.
  123.  
  124.    Information on contacting the author is provided at the end of this
  125. file.
  126.  
  127.  
  128. II. COMPILING AND LINKING WITH THE LIBRARIES
  129. --------------------------------------------
  130.  
  131.    This section describes how to use the XMSIF libraries with your
  132. programs.
  133.  
  134.    XMSIF is provided as Borland/Microsoft standard library files.
  135. Libraries are provided for small, medium, compact, large, and huge
  136. memory models (tiny model uses the small model library). The model for
  137. which a library is intended is indicated by the last letter of the
  138. filename proper, which is the same as the first letter for the model.
  139. For example, XMSIFL.LIB is the large model library.
  140.  
  141.  II.1 WITH C
  142.  -----------
  143.  
  144.    To use XMSIF in C programs, you must #include the file XMSIF.H in
  145. every source file that calls XMSIF functions, accesses XMSIF global
  146. variables, or uses #defined constants provided by XMSIF.
  147.  
  148.    The procedures for linking XMSIF with the rest of your program vary
  149. according to the compiler and method you are using. In general, you must
  150. include the appropriate library (the library corresponding to the memory
  151. model in which you have compiled the rest of your program) in the link.
  152.  
  153.    If you are compiling in the Integrated Development Environment of
  154. Turbo/Borland C[++], you should include the name of the appropriate
  155. library in the project file for your program. For example, if you are
  156. working in the compact memory model, you should include XMSIFC.LIB in
  157. your project file.
  158.  
  159.    If you are using a command-line compiler (bcc, tcc, or cl) to compile
  160. and link, simply place the full name of the appropriate XMSIF library on
  161. the command line. For example, "bcc -mc foo.c xmsifc.lib" will compile
  162. the file "foo.c" in the compact model and link it with xmsifc.lib.
  163.  
  164.    If you are linking manually (using TLINK or LINK), place the name of
  165. the appropriate library in with the other libraries. For example,
  166.         tlink c0c.obj foo.obj, foo.exe, foo.map, cc.lib xmsifc.lib
  167. or
  168.         link foo.obj, foo.exe, foo.map, xmsifc.lib ;
  169. will link the object "foo.obj" with the appropriate startup object and
  170. standard library (LINK automatically includes the startup object and
  171. standard library, so it is not necessary to explicitly include them) and
  172. the compact model XMSIF library.
  173.  
  174.  II.2 C++
  175.  --------
  176.  
  177.    To use XMSIF in C++ programs, you must #include the file XMSIF.HPP in
  178. every file that calls XMSIF functions, accesses XMSIF global variables,
  179. or uses #defined constants provided by XMSIF. Be careful to include
  180. XMSIF.HPP instead of XMSIF.H. If you include the wrong one, you will
  181. probably see "undefined symbol" errors when linking.
  182.  
  183.    Otherwise, the procedures for using XMSIF with C++ programs are the
  184. same as for using it with C programs.
  185.  
  186.  II.3 XMSTEST, THE EXAMPLE PROGRAM
  187.  ---------------------------------
  188.  
  189.    A large and complete example program and tester, XMSTEST, has been
  190. included in this distribution. It can be compiled in any of the
  191. supported memory models, with either Borland or Microsoft compilers.
  192.  
  193.    The test program has four source files: XMSTEST.C, XMSTEST2.C,
  194. XMSTEST3.C, and TESTUTIL.C, and two header files: XMSTEST.H and
  195. TESTUTIL.H. When compiling in tiny model with Borland compilers, an
  196. additional file, STACK.OBJ, is needed. STACK.ASM, which is the source
  197. for STACK.OBJ, has been included for completeness.
  198.  
  199.    Example makefiles have been included for Borland and Microsoft
  200. compilers. EXMAKEBC is the example makefile for Borland C++ 2.0,
  201. EXMAKETC is the example makefile for Turbo C[++], and EXMAKEMS is the
  202. example makefile for Microsoft C. Complete instructions for making the
  203. example program and using the example makefiles are included at the
  204. beginning of each makefile. More information about the program is also
  205. included at the beginning of XMSTEST.C.
  206.  
  207.    XMSTEST requires a single free EMB of at least 81,920 bytes in order
  208. to perform the copy-function tests. It requires at least one free UMB in
  209. order to perform all the UMB-function tests. If your system does not
  210. support UMBs, XMSTEST will note this fact and skip inappropriate
  211. UMB-function tests. If your system does support UMBs but none are free,
  212. XMSTEST will assume that your system does not support UMBs and will also
  213. skip inappropriate UMB-function tests. XMSTEST also requires at least
  214. 165,000 bytes of available conventional memory to run.
  215.  
  216.    XMSTEST may require the command-line parameters "-q" or "-w" to run
  217. on your system. You may also wish to use the "-3" parameter to perform
  218. more complete testing if your system is a 386 or better. A full
  219. explanation of these parameters and what they do may be found at the
  220. beginning of XMSTEST.C.
  221.  
  222.  
  223. III. PROGRAMMING WITH XMSIF
  224. ---------------------------
  225.  
  226.    This section describes how to make XMSIF calls in your program, and
  227. details various tricks and tips which you may find useful.
  228.  
  229.  III.1 INITIALIZATION
  230.  --------------------
  231.  
  232.    The library initialization function XMMlibinit() _must_ be called
  233. before any other XMSIF calls are made. All other XMSIF functions are
  234. guaranteed to fail if called before XMMlibinit(). XMMlibinit()
  235. determines whether an XMS driver is present and sets up various internal
  236. and global variables necessary to the functioning of XMSIF.
  237.  
  238.  
  239.  III.2 ORDINARY USE
  240.  ------------------
  241.  
  242.    XMSIF provides several sets of functions. First, there is a set of
  243. functions which are intended to be orthogonal with the standard C
  244. functions malloc(), realloc(), and free(), and the Borland/Turbo C[++]
  245. function coreleft(), for EMBs. These functions are XMMalloc(),
  246. XMMrealloc(), XMMfree(), XMMcoreleft(), and XMMallcoreleft().
  247.  
  248.    Second, there is a group of functions for copying data to and from
  249. EMBs. These functions are XMMcopyto(), XMMcopyfrom(), _XMMcopy(),
  250. XMMicopyto(), XMMicopyfrom(), and _XMMicopy().
  251.  
  252.    Third, there is a group of miscellaneous functions: XMMlibinit(),
  253. XMMgetversion(), XMMrawcall(), and XMMraw3().
  254.  
  255.    Finally, there is a set of functions which are intended to be
  256. orthogonal with the standard C functions malloc() and free(), and the
  257. Borland/Turbo C[++] function coreleft(), for UMBs. These functions are
  258. UMBalloc(), UMBfree(), UMBcoreleft(), and UMBallcoreleft(). For details
  259. on these functions and all the others listed above, see section IV.2.
  260.  
  261.    To use EMBs (Extended Memory Blocks), first it is necessary to
  262. allocate some. This is done with XMMalloc(), which takes a size in bytes
  263. and returns a handle which will be used to reference the allocated
  264. memory. EMBs are subject to fragmentation problems; it is not possible
  265. to allocate with XMMalloc() more extended memory than is in the largest
  266. free block. The size of the largest free block, in bytes, is returned by
  267. XMMcoreleft(). The total of all free EMBs is returned by
  268. XMMallcoreleft(). Other considerations about using EMBs are discussed in
  269. section III.3 below. To adjust the size of an existing EMB, use
  270. XMMrealloc().
  271.  
  272.    The only way to get data to or from an EMB is via the XMS driver's
  273. copying functions. The XMSIF copying functions provide handy interfaces
  274. to the underlying driver functions and provide extra processing to
  275. remove some of the limitations on the driver functions (such as the
  276. inability to copy an odd number of bytes).
  277.  
  278.    The miscellaneous functions listed above initialize XMSIF
  279. (XMMlibinit(), see section III.1), return the XMS version implemented by
  280. the driver (XMMgetversion()), and allow programs to call the driver more
  281. directly, specifying values for all the relevant registers
  282. (XMMrawcall() and XMMraw3()).
  283.  
  284.    Finally, to use UMBs (Upper Memory Blocks, which may exist in unused
  285. spaces between 640K and 1M), first it is necessary to allocate one (or
  286. more). This is done with UMBalloc(), which takes a size in bytes and
  287. returns a far pointer to the UMB. UMBs are subject to fragmentation
  288. problems; it is not possible to allocate with UMBalloc() more memory
  289. than is in the largest free block. The size of the largest free block,
  290. in bytes, is returned by UMBcoreleft(). The total of all free UMBs is
  291. returned by UMBallcoreleft(). Other problems with using UMBs are
  292. discussed in section III.4 below. Since UMBs can be accessed directly,
  293. no copying functions are provided for them.
  294.  
  295.    Many functions return a status directly. For those functions, a
  296. return value of 0 indicates success and a return value of XMMOOPS
  297. indicates failure. The global variable _XMMerror contains an error code
  298. which gives further information on why the function failed, or has value
  299. 0 if the function succeeded. Many functions return some other value
  300. instead of a status code (0 or XMMOOPS). In these cases, the value of
  301. _XMMerror should be checked upon return. The recommended method of
  302. error-checking is indicated for each function in section IV.2 below.
  303.  
  304.  III.3 TIPS ON USING EMBS
  305.  ------------------------
  306.  
  307.    As mentioned above, EMBs are subject to fragmentation problems, and
  308. the limit on allocation is the size of the largest free block. This has
  309. some interesting side effects. For one, there is no single measure of
  310. free extended memory. In some cases, the size of the largest free block
  311. will be most useful, in other cases, the total of all free blocks. Thus,
  312. both XMMcoreleft() and XMMallcoreleft() are provided. But a consequence
  313. of having multiple measures is that allocations may change the values in
  314. unanticipated ways. For example, while any allocation will change the
  315. total of all free blocks, it may or may not change the size of the
  316. largest free block depending on the size of the allocation request and
  317. the allocation strategy followed by the XMS driver. For example, if the
  318. allocation request is small enough to fit into a smaller free block, the
  319. XMS driver may perform the allocation from the smaller block, leaving
  320. the size of the largest free block unchanged. Or it may always perform
  321. allocations from the largest free block, in which case the size of the
  322. largest free block will change. In summary, do not depend on the size of
  323. the largest free block changing when you allocate extended memory.
  324.  
  325.    Furthermore, not all XMS drivers behave in exactly the same way.
  326. While writing XMSTEST, I observed distinct differences between QEMM 5.12
  327. and HIMEM.SYS 2.77. The most obvious difference is that when allocating
  328. under QEMM, the total of all free blocks drops by the size of the
  329. allocation rounded up to the nearest 16K, instead of the size rounded up
  330. to the nearest 1K (the minimum allocation unit for EMBs). This is
  331. probably related to QEMM's support of EMS, which has a minimum
  332. allocation unit of 16K. XMSTEST's -q parameter is a direct response to
  333. this difference in behavior. When allocating from a DOS session under
  334. MS-Windows 3.1, the total of all free blocks drops by the size of the
  335. allocation rounded up to the nearest 4K. This is probably because the
  336. 386 supports memory mapping in units of 4K. XMSTEST's -w parameter is a
  337. direct response to this difference in behavior. In summary, do not
  338. depend on the total of all free blocks changing by the amount you think
  339. it will.
  340.  
  341.    Finally, there are some speed considerations when using EMBs. For
  342. maximum speed, copy the largest blocks you can. Each copy of an even
  343. number of bytes makes one call to the XMS driver. Each copy of an odd
  344. number of bytes makes two calls to the XMS driver. And each copy of a
  345. single byte requires three calls to the XMS driver in order to reliably
  346. copy the desired byte without corrupting surrounding data (remember that
  347. the XMS driver itself can only copy even numbers of bytes). To get a
  348. good idea of relative speeds of various sizes of copies, run XMSTEST --
  349. it performs some speed tests, returning times in ticks (at 18.2 ticks
  350. per second). Large copies may be hundreds of times faster than multiple
  351. small copies to move the same number of bytes. If you have to make lots
  352. of small copies, try using the interval copy functions (_XMMicopy() et
  353. al.). They make the same number of calls to the XMS driver, but the
  354. loops are tightly coded in assembly and are marginally faster than
  355. performing the same loop yourself. And, as a last consideration, note
  356. that different XMS drivers may be faster or slower. Results from XMSTEST
  357. showed that QEMM was roughly 40% faster than HIMEM.SYS.
  358.  
  359.  III.4 TIPS ON USING UMBS
  360.  ------------------------
  361.  
  362.    It is probably better not to use UMBs if there isn't a powerful
  363. reason to do so. UMBs are not present on many systems, may be all used
  364. on other systems, and some XMS drivers have buggy UMB support functions.
  365.  
  366.    UMBs are blocks of memory between 640K (the top of conventional
  367. memory) and 1M (in general, the top of memory addressable in real mode).
  368. Systems based on the 80286 do not have UMBs unless there is special
  369. hardware support on the motherboard or elsewhere. Even if the hardware
  370. support is present, an XMS driver is also required to provide the UMB
  371. management functions. Systems based on the 80386 and up do not require
  372. the hardware support, but do require a driver (such as QEMM, EMM386.SYS,
  373. 386-to-the-Max, etc.) which uses the processor's on-board memory mapping
  374. capability to make extended memory appear between 640K and 1M, in unused
  375. holes between video memory, ROMs, and anything else inhabiting that
  376. space. Then they may require a separate XMS driver to actually provide
  377. the UMB management functions. QEMM and 386-to-the-Max include XMS
  378. drivers within themselves; EMM386.SYS requires HIMEM.SYS.
  379.  
  380.    Even if the system has the requisite support and drivers, UMBs may
  381. not be available to your application. DOS 5.0, for example, depending on
  382. the configuration, may allocate all UMBs to itself.
  383.  
  384.    Lastly, some XMS drivers have buggy UMB support functions. While
  385. testing XMSIF, I discovered that QEMM 5.12 may return a random error
  386. code when there are no more free UMBs. In fact, it may not return an
  387. error code at all -- it may leave the contents of that register
  388. untouched. Various measures to combat this problem have been taken
  389. within XMSIF with sufficient success that XMSTEST can perform the
  390. UMB-function tests under QEMM 5.12 correctly, but other XMS drivers may
  391. have other bugs. In summary, I would advise that you avoid the use of
  392. UMBs unless there is a powerful reason to do so, and even then your
  393. program should be ready to deal with error returns or unusual results.
  394.  
  395.  III.5 OTHER TIPS
  396.  ----------------
  397.  
  398.    Neither EMBs nor UMBs are deallocated automatically when a program
  399. exits. If the program does not deallocate EMBs or UMBs that it has
  400. allocated, those EMBs and/or UMBs are stuck, not available to any other
  401. program until the machine is rebooted. Under normal circumstances, it is
  402. easy enough to free EMBs and UMBs when they are no longer needed.
  403. However, an emergency exit due to the user hitting control-break or due
  404. to a hardware error (e.g. the famous "Abort, Retry, Fail?") can cause
  405. EMBs or UMBs to become stuck unless your program takes special measures
  406. to intercept these errors and perform cleanup before exiting. There are
  407. a number of ways to do this and they vary from compiler to compiler.
  408. Look for functions named things like ctrlbrk(), harderr(), and signal().
  409.  
  410.    If you are copying array elements, XMMicopyto(), XMMicopyfrom(), or
  411. _XMMicopy() may be more efficient. These functions allow copying of
  412. elements of fixed size which are separated by gaps also of fixed size.
  413. For example, if you have an array of integers and wish to copy all the
  414. even-indexed elements (a[0], a[2], a[4], etc.), these functions are
  415. faster than calling a standard copying function (XMMcopyto(),
  416. XMMcopyfrom(), or _XMMcopy()) from within a loop.
  417.  
  418.  III.6 FUNCTION GROUPING
  419.  -----------------------
  420.  
  421.    The XMSIF functions have been arranged in the library in such a way
  422. as to reduce the number of unnecessary functions linked into your
  423. program. There are currently two groups:
  424.  
  425.                 FUNCTIONS                               VARIABLES
  426.                 ---------                               ---------
  427. GROUP 1:        XMMlibinit(), XMMgetversion(),          _XMMerror, _XMMversion,
  428.                 XMMcoreleft(), XMMallcoreleft(),        _xmsif_vers_vers,
  429.                 XMMalloc(), XMMrealloc(), XMMfree(),    _xmsif_vers_date,
  430.                 _XMMcopy(), _XMMicopy()                 _xmsif_vers_time
  431.  
  432. GROUP 2:        UMBcoreleft(), UMBallcoreleft(),        none
  433.                 UMBalloc(), UMBfree()
  434.  
  435. GROUP 3:        XMMrawcall(), XMMraw3()                 none
  436.  
  437. If your program references any of the functions or variables in a group,
  438. all the functions and variables in that group will be linked in. Note
  439. that group one will always be linked, since it contains XMMlibinit(),
  440. which all XMSIF-using programs must call.
  441.  
  442.  
  443. IV. LIBRARY REFERENCE
  444. ---------------------
  445.  
  446.  IV.1 GLOBAL VARIABLES
  447.  ---------------------
  448.  
  449.   _XMMerror
  450.   ---------
  451.  
  452.    unsigned char const _XMMerror;
  453.  
  454.    _XMMerror contains the error code from the last XMSIF call. If the
  455. call succeeded, _XMMerror will be 0. If the call failed because the XMS
  456. driver returned an error, _XMMerror contains the error code returned by
  457. the XMS driver. If the call failed because XMSIF detected an error
  458. internally, _XMMerror contains an internal error code. A list of error
  459. code values, their meanings, and #defined constants for them is in
  460. section V.
  461.  
  462.   _XMMversion
  463.   -----------
  464.  
  465.    unsigned int const _XMMversion;
  466.  
  467.    _XMMversion contains the XMS version implemented by the XMS driver in
  468. packed BCD format. For example, if the XMS version is 2.0, the value of
  469. _XMMversion will be 0x0200. The high byte of _XMMversion represents two
  470. digits to the left of the decimal point (one digit per nibble) and the
  471. low byte represents two digits to the right of the decimal point (again,
  472. one digit per nibble). This value is the same as that returned by
  473. XMMgetversion().
  474.  
  475.   xmsif_vers_vers, xmsif_vers_date, xmsif_vers_time
  476.   -------------------------------------------------
  477.  
  478.    char const xmsif_vers_vers[];
  479.    char const xmsif_vers_date[];
  480.    char const xmsif_vers_time[];
  481.  
  482.    These are null-terminated strings containing information about the
  483. name and version of the library, the date of assembly, and the time of
  484. assembly, respectively.
  485.  
  486.  IV.2 EMB FUNCTIONS
  487.  ------------------
  488.  
  489.   _XMMcopy() - copy data
  490.   ----------
  491.  
  492.    int _XMMcopy(unsigned long clen,
  493.                 int shan, unsigned long soff,
  494.                 int dhan, unsigned long doff);
  495.    int XMMcopyfrom(unsigned long clen,
  496.                    int handle, unsigned long soff,
  497.                    unsigned char far *dest);
  498.    int XMMcopyto(unsigned long clen,
  499.                  unsigned char far *src,
  500.                  int handle, unsigned long doff);
  501.  
  502.    _XMMcopy() allows painless copying from conventional memory to an
  503. EMB, from an EMB to conventional memory, from one EMB to another, or
  504. even from one point in conventional memory to another. Areas larger than
  505. 64K can be copied without special treatment. Clen bytes of data are
  506. copied. If shan is nonzero, it is assumed to be the handle of an EMB,
  507. and soff is treated as a byte offset into the EMB owned by shan. If shan
  508. is zero, soff is treated as a segment:offset far pointer to conventional
  509. memory. The pair of shan and soff indicate where the data is to be
  510. copied from (the source). Dhan and doff work similarly, but indicate
  511. where the data is to be copied to (the destination).
  512.    This function returns 0 on success or XMMOOPS on error. The specific
  513. error may be determined from _XMMerror. If clen is 0, the function
  514. returns immediately without error.
  515.  
  516.    XMMcopyfrom() is a macro which provides a convenient interface to
  517. _XMMcopy() for copying data from an EMB to conventional memory. Clen
  518. bytes of data are copied. Handle is the handle of an EMB, and soff is a
  519. byte offset into the EMB owned by handle. The pair of handle and soff
  520. indicate where the data is to be copied from. Dest is a far pointer to
  521. conventional memory and indicates where the data is to be copied to. The
  522. returns are the same as for _XMMcopy().
  523.  
  524.    XMMcopyto() is a macro which provides a convenient interface to
  525. _XMMcopy() for copying data to an EMB from conventional memory. Clen
  526. bytes of data are copied. Src is a far pointer to conventional memory
  527. and indicates where the data is to be copied from. Handle is the handle
  528. of an EMB, and doff is a byte offset into the EMB owned by handle. The
  529. pair of handle and doff indicate where the data is to be copied to. The
  530. returns are the same as for _XMMcopy().
  531.  
  532.   _XMMicopy() - copy data by intervals
  533.   -----------
  534.  
  535.    int _XMMicopy(unsigned long nelem, int elsize,
  536.                  unsigned int sskip, int shan, unsigned long soff,
  537.                  int dhan, unsigned long doff, unsigned int dskip);
  538.    int XMMicopyfrom(unsigned long nelem, int elsize, unsigned int byteskip,
  539.                     int handle, unsigned long soff,
  540.                     unsigned char far *dest);
  541.    int XMMicopyto(unsigned long nelem, int elsize, unsigned int byteskip,
  542.                   unsigned char far *src,
  543.                   int handle, unsigned long doff);
  544.  
  545.    _XMMicopy() allows painless copying of array elements from
  546. conventional memory to an EMB, from an EMB to conventional memory, from
  547. one EMB to another, or even from one point in conventional memory to
  548. another. Calculation of addresses, skipping of unwanted elements, etc.,
  549. are all handled by the function. Elements spread across more than 64K
  550. or totalling more than 64K in length can be copied without special
  551. treatment.
  552.    Nelem elements are copied, each of which is elsize bytes long. If
  553. shan is nonzero, it is assumed to be the handle of an EMB, and soff is
  554. treated as a byte offset into the EMB owned by shan. If shan is zero,
  555. soff is treated as a segment:offset far pointer to conventional memory.
  556. The pair of shan and soff indicate where the data is to be copied from
  557. (the source). Dhan and doff work similarly, but indicate where the data
  558. is to be copied to (the destination). Sskip and dskip indicate the
  559. number of bytes between elements in the source and destination,
  560. respectively.
  561.    If nelem or elsize is zero, the function returns immediately without
  562. error. If nelem is one, _XMMcopy() is called internally. Elsize must be
  563. in the range 0 through 16384, or the function will return with error
  564. XMM_ELTOOBIG (in _XMMerror). Sskip and dskip must both be in the range 0
  565. through 32768, or the function will return with error XMM_SKTOOBIG (in
  566. _XMMerror).
  567.    This function returns 0 on success or XMMOOPS on error. The specific
  568. error may be determined from _XMMerror.
  569.  
  570.    XMMicopyfrom() is a macro which provides a more convenient interface
  571. to _XMMicopy() for copying data from an EMB to conventional memory with
  572. sskip equal to dskip. Nelem elements are copied, each of which is elsize
  573. bytes long. Handle is the handle of an EMB, and soff is a byte offset
  574. into the EMB owned by handle. The pair of handle and soff indicate where
  575. the data is to be copied from. Dest is a far pointer to conventional
  576. memory and indicates where the data is to be copied to. Byteskip is the
  577. number of bytes between elements, the same for both source and
  578. destination. The returns are the same as for _XMMicopy().
  579.  
  580.    XMMicopyto() is a macro which provides a more convenient interface
  581. to _XMMicopy() for copying data to an EMB from conventional memory with
  582. sskip equal to dskip. Nelem elements are copied, each of which is elsize
  583. bytes long. Src is a far pointer to conventional memory and indicates
  584. where the data is to be copied from. Handle is the handle of an EMB, and
  585. doff is a byte offset into the EMB owned by handle. The pair of handle
  586. and doff indicate where the data is to be copied to. Byteskip is the
  587. number of bytes between elements, the same for both source and
  588. destination. The returns are the same as for _XMMicopy().
  589.  
  590.   XMMallcoreleft() - get total of all free EMBs
  591.   ----------------
  592.  
  593.    unsigned long XMMallcoreleft(void);
  594.    unsigned long XMMcoreleft(void);
  595.  
  596.    XMMallcoreleft() returns the total size of all free EMBs, in bytes.
  597. Note that when all EMBs have been allocated, the driver itself returns
  598. an error (0xA0, XMM_NOFREEX). This behavior is masked by
  599. XMMallcoreleft() -- if there are no free EMBs, XMMallcoreleft() returns
  600. 0L, not an error. _XMMerror should be checked after calling this
  601. function (it is reset to 0 if there are no free EMBs).
  602.  
  603.    XMMcoreleft() returns the size of the largest free EMB, in bytes.
  604. Note that when all EMBs have been allocated, the driver itself returns
  605. an error (0xA0, XMM_NOFREEX). This behavior is masked by XMMcoreleft() --
  606. if there are no free EMBs, XMMcoreleft() returns 0L, not an error.
  607. _XMMerror should be checked after calling this function (it is reset to
  608. 0 if there are no free EMBs).
  609.  
  610.   XMMalloc() - allocate EMB
  611.   ----------
  612.  
  613.    int XMMalloc(unsigned long bytes);
  614.    int XMMrealloc(int handle, unsigned long bytes)
  615.  
  616.    XMMalloc() allocates an EMB. It takes the given number of bytes
  617. and rounds it up to the nearest kilobyte, then allocates an EMB that
  618. many kilobytes in size. It returns the EMB handle assigned by the XMS
  619. driver. _XMMerror should be checked after calling this function.
  620.    Note that EMBs cannot be allocated in units smaller than a kilobyte
  621. (1024 bytes). Requesting one byte will allocate 1K; 1025 bytes will
  622. allocate 2K. Requesting zero bytes allocates a handle but no memory.
  623.    Note that it is not possible to allocate in one XMMalloc() call more
  624. extended memory than is in the largest free EMB. This is a limitation of
  625. the XMS driver. See section III.3 above for more information on EMB
  626. allocation limitations.
  627.  
  628.    XMMrealloc() adjusts the size of an EMB previous allocated with
  629. XMMalloc(). Handle is the handle of the EMB to be adjusted. The given
  630. number of bytes is rounded up to the nearest kilobyte, then the EMB is
  631. adjusted to that size, if possible. XMMrealloc() returns the handle of
  632. the new block, which is always the same as the handle of the old block.
  633. _XMMerror should be checked after calling this function.
  634.  
  635.   XMMcopyfrom() - copy data from EMB
  636.   -------------
  637.  
  638.    int XMMcopyfrom(unsigned long clen,
  639.                    int handle, unsigned long soff,
  640.                    unsigned char far *dest);
  641.  
  642.    See _XMMcopy().
  643.  
  644.   XMMcopyto() - copy data to EMB
  645.   -----------
  646.  
  647.    int XMMcopyto(unsigned long clen,
  648.                  unsigned char far *src,
  649.                  int handle, unsigned long doff);
  650.  
  651.    See _XMMcopy();
  652.  
  653.  
  654.   XMMcoreleft() - get size of largest free EMB
  655.   -------------
  656.  
  657.    unsigned long XMMcoreleft(void);
  658.  
  659.    See XMMallcoreleft().
  660.  
  661.   XMMfree() - deallocate an EMB
  662.   ---------
  663.  
  664.    int XMMfree(int handle);
  665.  
  666.    This function accepts an EMB handle (as returned by XMMalloc() or
  667. otherwise obtained from the XMS driver) and releases it and the EMB
  668. associated with it (if any). This function returns 0 on success or
  669. XMMOOPS on error. The specific error may be determined from _XMMerror.
  670.  
  671.   XMMgetversion() - obtain XMS version implemented by XMS driver
  672.   ---------------
  673.  
  674.    int XMMgetversion(void);
  675.  
  676.    This function returns the XMS version implemented by the XMS driver.
  677. The version number is in packed BCD format as in the global variable
  678. _XMMversion, and is in fact the same value. _XMMerror should be checked
  679. after calling this function.
  680.  
  681.   XMMicopyfrom() - copy data by intervals from EMB
  682.   --------------
  683.  
  684.    int XMMicopyfrom(unsigned long nelem, int elsize, unsigned int byteskip,
  685.                     int handle, unsigned long soff,
  686.                     unsigned char far *dest);
  687.  
  688.    See _XMMicopy().
  689.  
  690.   XMMicopyto() - copy data by intervals to EMB
  691.   ------------
  692.  
  693.    int XMMicopyto(unsigned long nelem, int elsize, unsigned int byteskip,
  694.                   unsigned char far *src,
  695.                   int handle, unsigned long doff);
  696.  
  697.    See _XMMicopy().
  698.  
  699.   XMMlibinit() - initialize XMSIF
  700.   ------------
  701.  
  702.    int XMMlibinit(void);
  703.  
  704.    XMMlibinit() initializes XMSIF. Any other XMSIF function will return
  705. with error XMM_NOINIT (in _XMMerror) if called before XMMlibinit() has
  706. been called. This function returns 0 on success, XMMOOPS on error, or
  707. NOXMM if no XMS driver is detected. The specific error may be determined
  708. from _XMMerror.
  709.  
  710.   XMMrawcall() - call XMS driver directly
  711.   ------------
  712.  
  713.    int XMMrawcall(struct XMMregs *regs);
  714.    void XMMraw3(struct XMMbigregs *regs);
  715.  
  716.    XMMrawcall() is a raw interface directly to the XMS driver,
  717. supporting calls which use only 16-bit registers. The XMMregs structure
  718. has fields for the AX, BX, DX, SI, and DS registers, which include all
  719. the 16-bit registers used as parameters for calls to the XMS driver. The
  720. values in the structure are placed in the appropriate registers before
  721. the XMS driver is called, and the registers are copied back into the
  722. structure after the XMS driver call returns. Check XMSIF.H or XMSIF.HPP
  723. for the exact format of the XMMregs structure.
  724.    Since the XMS specification provides a uniform error indication for
  725. all XMS calls, XMMrawcall() is able to determine if the call performed
  726. caused an error. It returns 0 on success or XMMOOPS on error. The
  727. specific error may be determined from _XMMerror; the error code can also
  728. be found in the low byte of the regBX field of the XMMregs structure.
  729.  
  730.    XMMraw3() is a raw interface directly to the XMS driver, supporting
  731. the calls added in version 3.0 which use 32-bit registers. The
  732. XMMbigregs structure has fields for the EAX, EBX, ECX, and EDX
  733. regusters, which include all the 32-bit registers used as parameters for
  734. calls to the XMS driver. The values in the structure are placed in the
  735. appropriate registers before the XMS driver is called, and the registers
  736. are copied back into the structure after the XMS driver call returns.
  737. Check XMSIF.H or XMSIF.HPP for the exact format of the XMMbigregs
  738. sturcture.
  739.    These calls do not provide a uniform error indication, so XMMraw3()
  740. does not return anything. The low 8 bits of EBX (register BL) are copied
  741. to _XMMerror, but they may not be meaningful. In general, it is
  742. necessary to look at the register contents to determine success or
  743. failure. Not all calls use all of each register, so be careful when
  744. examining values. If the XMS driver is version 2.0, _XMMerror is set to
  745. XMM_BADVERS.
  746.    Note that this function must not be used on 286 (or earlier)
  747. machines. It uses 386 instructions to access the registers, which will
  748. probably crash older processors. Furthermore, HIMEM versions 3.03
  749. through 3.07 are known to crash when these calls are made on 286 or
  750. earlier machines. It is up to the application to ensure that this call
  751. is only used on 386 or better machines.
  752.  
  753.   XMMraw3() - call XMS driver directly with extended registers
  754.   ---------
  755.  
  756.    See XMMrawcall().
  757.  
  758.   XMMrealloc() - adjust the size of an EMB
  759.   ------------
  760.  
  761.    See XMMalloc().
  762.  
  763.  IV.3 UMB FUNCTIONS
  764.  ------------------
  765.  
  766.   UMBallcoreleft() - get total of all free UMBs
  767.   ----------------
  768.  
  769.    unsigned long UMBallcoreleft(void);
  770.    unsigned long UMBcoreleft(void);
  771.  
  772.    UMBallcoreleft() returns the total size of all free UMBs, in bytes.
  773. Note that when all UMBs have been allocated, the driver itself returns
  774. an error (0xB1, UMB_NOFREEUMB). This behavior is masked by
  775. UMBallcoreleft() -- if there are no free UMBs, UMBallcoreleft() returns
  776. 0L, not an error. If the XMS driver does not support UMBs at all, it
  777. returns an error (0x80, XMM_UNIMP). This is also masked by
  778. UMBallcoreleft(). Again, 0L will be returned, not an error. _XMMerror
  779. should be checked after calling this function (it is reset to 0 when a
  780. masked error occurs).
  781.  
  782.    UMBcoreleft() returns the size of the largest free UMB, in bytes.
  783. Note that when all UMBs have been allocated, the driver itself returns
  784. an error (0xB1, UMB_NOFREEUMB). This behavior is masked by UMBcoreleft() --
  785. if there are no free UMBs, UMBcoreleft() returns 0L, not an error. If
  786. the XMS driver does not support UMBs at all, it returns an error (0x80,
  787. XMM_UNIMP). This is also masked by UMBallcoreleft(). Again, 0L will be
  788. returned, not an error. _XMMerror should be checked after calling this
  789. function (it is reset to 0 when a masked error occurs).
  790.  
  791.   UMBalloc() - allocate UMB
  792.   ----------
  793.  
  794.    void far *UMBalloc(unsigned long bytes, unsigned long *finalsize);
  795.  
  796.    This function allocates an UMB. It takes the given number of bytes
  797. and rounds it up to the nearest multiple of 16, then allocates a UMB
  798. that many bytes in size. The actual size in bytes of the UMB allocated
  799. is returned in the unsigned long pointed to by finalsize. UMBalloc()
  800. returns a far pointer to the UMB; this pointer should be cast to a type
  801. other than void before being used to access the UMB. _XMMerror should be
  802. checked after calling this function.
  803.    Note that UMBs cannot be allocated in units smaller than a paragraph
  804. (16 bytes). Requesting one byte will allocate 16; 17 bytes will allocate
  805. 32.
  806.    Note that it is not possible to allocate in one UMBalloc() call more
  807. extended memory than is in the largest free UMB. This is a limitation of
  808. the XMS driver. See section III.4 above for more information on UMB
  809. allocation limitations.
  810.  
  811.   UMBcoreleft() - get size of largest free UMB
  812.   -------------
  813.  
  814.    unsigned long UMBcoreleft(void);
  815.  
  816.    See UMBallcoreleft().
  817.  
  818.   UMBfree() - deallocate an UMB
  819.   ---------
  820.  
  821.    int UMBfree(void far *handle);
  822.  
  823.    This function accepts a pointer to a UMB (as returned by UMBalloc())
  824. and releases that UMB. If the pointer has been modified, UMBfree()
  825. attempts to return it to canonical form before calling the XMS driver.
  826. However, for maximum reliability, UMBfree() should be called with an
  827. unmodified copy of the pointer returned by UMBalloc(). This function
  828. returns 0 on success or UMBOOPS on error. The specific error may be
  829. determined from _XMMerror.
  830.  
  831.  
  832. V. ERROR CODES
  833. --------------
  834.  
  835.    This section is a list of the error codes to which the global
  836. variable _XMMerror may be set, and the values and meanings thereof.
  837.  
  838.  V.1 INTERNAL ERRORS
  839.  -------------------
  840.  
  841.    Internal codes indicate an error detected by XMSIF itself.
  842.  
  843.    NAME                 VALUE     MEANING
  844.    ----                 -----     -------
  845.    XMM_NOINIT            0x40     XMMlibinit() must be called before any
  846.                                   other XMSIF function can be called.
  847.  
  848.    XMM_UMBHUGE           0x41     Size of UMB requested is larger than
  849.                                   XMS driver can handle (maximum UMB
  850.                                   request size is 1M).
  851.  
  852.    XMM_BADPTR            0x42     The UMB pointer passed to UMBfree()
  853.                                   is corrupt.
  854.  
  855.    XMM_ELTOOBIG          0x43     The element size passed to XMMicopyto(),
  856.                                   XMMicopyfrom(), or _XMMicopy() is too big.
  857.  
  858.    XMM_SKTOOBIG          0x44     The skip size passed to XMMicopyto(),
  859.                                   XMMicopyfrom(), or _XMMicopy() is too big.
  860.  
  861.    XMM_BADVERS           0x45     Certain functions are not supported
  862.                                   under XMS version 2.0.
  863.  
  864.  V.2 XMS DRIVER ERRORS
  865.  ---------------------
  866.  
  867.    These codes are defined in the XMS specification and are returned by
  868. the XMS driver. They are saved in _XMMerror by XMSIF without alteration.
  869.  
  870.    NAME                 VALUE     MEANING
  871.    ----                 -----     -------
  872.    XMM_UNIMP             0x80     Function is not implemented
  873.  
  874.    XMM_VDISK             0x81     VDISK device driver was detected
  875.  
  876.    XMM_A20ERROR          0x82     A20 error occurred
  877.  
  878.    XMM_GENERROR          0x83     General driver error occurred
  879.  
  880.    XMM_UNRECERROR        0x84     Unrecoverable driver error occurred
  881.  
  882.    XMM_NOHMA             0x90     HMA (High Memory Area) does not exist
  883.  
  884.    XMM_HMAUSED           0x91     HMA already allocated
  885.  
  886.    XMM_HMATOOBIG         0x92     Request to allocate HMA denied because
  887.                                   amount of HMA requested is less than
  888.                                   minimum parameter given to XMS driver
  889.                                   on its command line
  890.  
  891.    XMM_HMANOALLOC        0x93     HMA is not allocated
  892.  
  893.    XMM_A20STILLEN        0x94     A20 line is still enabled
  894.  
  895.    XMM_NOFREEX           0xA0     All EMBs (Extended Memory Blocks) are
  896.                                   allocated
  897.  
  898.    XMM_NOFREEXHAN        0xA1     No free EMB handles
  899.  
  900.    XMM_BADXHAN           0xA2     EMB handle is invalid
  901.  
  902.    XMM_BADSRCHAN         0xA3     Source EMB handle is invalid
  903.  
  904.    XMM_BADSRCOFF         0xA4     Source offset in EMB is beyond end of EMB
  905.  
  906.    XMM_BADDESTHAN        0xA5     Destination EMB handle is invalid
  907.  
  908.    XMM_BADDESTOFF        0xA6     Destination offset in EMB is beyond end
  909.                                   of EMB
  910.  
  911.    XMM_BADLENGTH         0xA7     Length is invalid
  912.  
  913.    XMM_COPYOVERLAP       0xA8     Overlap in copy request is invalid
  914.  
  915.    XMM_PARITY            0xA9     Parity error was detected
  916.  
  917.    XMM_NOLOCK            0xAA     EMB is not locked
  918.  
  919.    XMM_LOCKED            0xAB     EMB is locked
  920.  
  921.    XMM_TOOMANYLOCKS      0xAC     EMB lock count overflowed
  922.  
  923.    XMM_LOCKFAIL          0xAD     EMB lock failed
  924.  
  925.    XMM_UMBSMALLER        0xB0     UMB (Upper Memory Block) of size requested
  926.                                   is not available; however, a smaller UMB
  927.                                   is available
  928.  
  929.    XMM_NOFREEUMB         0xB1     All UMBs are allocated
  930.  
  931.    XMM_BADUMBHAN         0xB2     UMB handle (same as segment address of
  932.                                   start of UMB) is invalid
  933.  
  934.  
  935. VI. THE END
  936. -----------
  937.  
  938.    Technical support via email is available from the following addresses:
  939.  
  940.    INTERNET:
  941.       The following are alternate addresses for the same place:
  942.          support@picarefy.com
  943.          picarefy!support@amc.com
  944.          picarefy!support@netcom.com
  945.          uunet!uw-coco!amc-gw!picarefy!support
  946.  
  947.    COMPUSERVE:
  948.       71261,1731
  949.  
  950.    GENIE:
  951.       J.BIRDSALL2
  952.  
  953.    Registrations should be sent to:
  954.  
  955.       James W. Birdsall
  956.       11112 NE 124 LN #D204
  957.       Kirkland, WA 98034
  958.  
  959.    If you have an email address on any of the networks listed above,
  960. please include it when registering, especially if you are requesting
  961. source code. It is much easier to send the source code by email. Also,
  962. please specify what sort of archive (ZIP, ZOO, ARC, LZH, ARJ, UNIX shar)
  963. you can handle most easily.
  964.  
  965.    NOTE: IF YOU DO NOT PROVIDE AN EMAIL ADDRESS, YOU WILL ONLY RECEIVE
  966. MAJOR VERSION UPDATES. YOU WILL NOT RECEIVE MINOR VERSIONS. PLEASE
  967. PROVIDE AN EMAIL ADDRESS IF YOU HAVE ANY WAY OF DOING SO.
  968.  
  969.  VI.1 ACKNOWLEDGEMENTS
  970.  ---------------------
  971.  
  972.    Thanks to Bob Parsons of Parsons Technology Inc. for some good suggestions
  973. on the documentation and for providing the original C++ header file.
  974.  
  975.